/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hecatone;

import java.io.*;
import java.util.*;
import java.sql.*;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.apache.log4j.PropertyConfigurator;
/**
 *
 * @author fredericpaquette
 */
public class Hecatone {

    /*
     * Variable declaration
     */
    public Hashtable gameproperties;
    public SqlCommands mysqlConnection;
    public int currentTick;
    public Hashtable characHash; 
            
            
            
   File properties;
   private static final Logger logger = Logger.getLogger(Hecatone.class);
   
    
    
    public static void main(String[] args) {
        
  
        Hecatone hecatone = new Hecatone();
        hecatone.init();
        hecatone.mainloop();
       
        
    }
    
    public void init()
    {
        PropertyConfigurator.configure("log4j.properties");
        logger.info("Log4j is initialized");
        gameproperties = loadProperties();
        logger.info("Game properties loaded");
        mysqlConnection = new SqlCommands(gameproperties);
        logger.info("Completed init");
        return;
    }
    public void mainloop()
    {
        ResultSet turn = mysqlConnection.getCurrentTurn();
        try{
           while(!turn.getBoolean("FINISHED"))
            {
                loadUnits();
            
         
        
               executeOrder850();
        
        
        
               mysqlConnection.updateTurnTick();
   
        
             logger.info("Sleeping till the next tick in "+Long.parseLong((String)gameproperties.get("ticktime"))+" minutes.");
             Thread.sleep(Long.parseLong((String)gameproperties.get("ticktime")) * 60000);
             turn = mysqlConnection.getCurrentTurn();
             mysqlConnection = new SqlCommands(gameproperties);
             //saveUnits();
            }
        }
        catch (SQLException sqle)
        {
            logger.error("Database error in main loop");
            logger.error(sqle.getMessage());
        }
        catch (InterruptedException ie)
        {
            logger.fatal("Interupted while sleeping");
            logger.fatal(ie.getMessage());
            System.exit(1);
        }
        
    }
    
    
 /*
     * Load all the game parameters and store in a Hashtable
     * 
     */
   public Properties loadProperties ()
    {
        Properties prop = new Properties();
        try
            {

                prop.load(new FileInputStream(new File("hecatone.properties")));
            }
                    catch(FileNotFoundException fne)
                {
                    logger.error(fne.getMessage());    }
                    catch(IOException io)
                    {
                        logger.error(io.getMessage());
                        logger.debug(io.getStackTrace());
                    }

        return prop;
      }
   

   
   /*************************************************
    * ExecuteOrders, this method will pull from the DB all orders for
    * the current tick that still have tick remaining for a given order number.
    * 
    *******************************************************/
  
   /*
    * Will move characters 
    */
   
   public boolean executeOrder850 ()
   {
       int nexthex;
       logger.info("Preparing to execute all 850 for this tick");
       ResultSet set = mysqlConnection.getOrdersToExecute(850);
       if (set == null)
       {
           logger.info("Either nobody did a 850 or query to db failed");
           return false;
       }
      
                            
       try
       {
           while(set.next())
           {
            logger.info (set.getString("nom"));
            //logger.info (set.getString("ARMEE_ID"));
            nexthex = testMovDirection(set.getString(10),set.getInt(8),set.getString("nom"));
            int remaintick = set.getInt("tick_restant");
            int orderid = set.getInt("ORDRE_ID");
            if (nexthex == 0)
                    {
                        logger.info("The selected direction is returning an invalid hex");
                        logger.info("I will still decrement the remaining tick for this move");
                        mysqlConnection.updateRemainingTick(orderid, remaintick);
                    }
            else
            {
                logger.info("We have a valid hex, now how many tick left");
                logger.info("The next hex for this move will be "+ nexthex);
                if (remaintick <= 1)
                {
                    logger.info("Will move the army to the next hex");
                    mysqlConnection.updateRemainingTick(orderid, remaintick);
                    mysqlConnection.moveCharacter(set.getInt("PERSO_ID"), nexthex, orderid);
                }
                else
                {
                    logger.info("Will remain in this hex for now, tick remaining till army moves: "+remaintick);
                    mysqlConnection.updateRemainingTick(orderid, remaintick);
                }
            }
            
           }
       }
       catch (SQLException sqle)
       {
           logger.error("Database error!");
           logger.error(sqle.getMessage());
           logger.debug(sqle.getStackTrace());
           return false;
       }
       return true;
   }
  
   

   
/******************************************************************************
    * This function does a basic check if the direction of the move for an army
    * is valid. Reason for the move to fail:
    * Trying to enter a see or deep sea hex, An ennemy army is entering the hex
    * from an opposite direction or adjacent to opposite direction. A mountain hex from a 
    * mountain hex.
    * 
    * @param Direction
    * @param hex
    * @return 
    */   
   
   
public int testMovDirection (String Direction, int hex, String nom)

{
    int nextHex;
    String[] comlist;

    ResultSet armiesInHex = mysqlConnection.checkForArmies(hex);
    
    nextHex = calculateNextHex(Direction, hex);
    logger.info("Next hex is "+ nextHex +" for army commander "+ nom);
    Vector coms = mysqlConnection.findBlockingComs(armiesInHex);
    
    return nextHex;
}
public int calculateNextHex(String Direction, int hex)

{
    logger.debug("In Calculate next hex, current hex = "+ hex);
    int nextHex = 0;
    
    if (Direction.matches("E"))
    {
        nextHex = hex + 100;
    }
    else if(Direction.matches("W"))
    {
        nextHex = hex - 100;        
    }

    if (hex % 2 == 0){
        logger.info("Hex is even");
        if (Direction.matches("NW"))
        {
            nextHex = hex - 1;
        }
        else if (Direction.matches("SW"))
        {
            nextHex = hex + 1;                    
        }
        else if (Direction.matches("NE"))
        {
            nextHex = hex + 99;
        }
        else if (Direction.matches("SE"))
        {
            nextHex = hex + 101;
        }
        
    }
    else {
        logger.info ("Hex is odd");
         if (Direction.matches("NW"))
        {
            nextHex = hex + 99;
        }
        else if (Direction.matches("SW"))
        {
            nextHex = hex + 101;                    
        }
        else if (Direction.matches("NE"))
        {
            nextHex = hex - 1;
        }
        else if (Direction.matches("SE"))
        {
            nextHex = hex + 1;
        }       
    }
    logger.debug("Before discarding the nexthex in calculateHex: "+ nextHex);
    
        if (mysqlConnection.doesHexExist(nextHex))
        {
            logger.info("Next hex is valid: "+ nextHex );
            return nextHex;
        }
        else
        {
            logger.info ("Next hex is not valid!");
            return 0;
        }
}

    public void loadUnits()
        {
            
            logger.debug("Entering load units phase for this turn");
            ResultSet characters = mysqlConnection.returnAllCharacters();
            if (characters == null)
            {
                logger.error("Characters failed to load");
                return;
            }
            characHash = new Hashtable();
            try{
                logger.debug("Turn: "+mysqlConnection.getTurnNumber());
            while(characters.next())
            {
                logger.debug("Loading "+ characters.getString("nom"));
                Character bobby = new Character(characters.getInt("PERSO_ID"),characters.getString("nom"));
                bobby.HEALTH = characters.getInt("sante");
                bobby.NATION_ID = characters.getInt("NATION_ID");
                bobby.agentLevel = characters.getInt("agent");
                bobby.challenge = characters.getInt("defi");
                bobby.commanderLevel = characters.getInt("commandeur");
                bobby.currenHex = characters.getInt("HEX_ID");
                bobby.emissaryLevel = characters.getInt("emissary");
                bobby.status = characters.getString("etat");
                
                if (this.mysqlConnection.isCharacterArmyLeader(characters.getInt("PERSO_ID")))
                {
                    logger.info("The character is leading an army");
                    loadArmies(bobby);
                }
                
                characHash.put(characters.getString("nom"), bobby);
            }
            }
            catch(SQLException sqle)
            {
                logger.error("Database error in loadunits() "+sqle.getMessage());
                return;
            }
            
        }
    
    /*
     * Loading armies in the character object
     * 
     */
    public void loadArmies(Character dendy)
        {
            try
            {
                this.mysqlConnection.army.setInt(1, dendy.PERSO_ID);
                ResultSet armyset = this.mysqlConnection.army.executeQuery();
                this.mysqlConnection.squads.setInt(1, dendy.PERSO_ID);
                ResultSet squadset = this.mysqlConnection.squads.executeQuery();
                
                while (squadset.next())
                {
                    
                }
            }
            catch(SQLException sqle)
            {
                logger.error("Database error in loadArmies "+ sqle.getMessage());
                
            }
        }
}